package com.zws.cucumber.util.colorfullog;

import org.apache.commons.lang3.SystemUtils;

import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * author: zws
 */
public class ZwsColorfulLogHelper {

    public static final String ESC_START = "\u001B[";
    public static final String ESC_END = "m";

    public static final String ANSI_RESET = "\u001B[0m";
//    public static final String FG_BLACK = "\u001B[30m";
    public static final String ANSI_RED = "\u001B[31m";
    public static final String ANSI_GREEN = "\u001B[32m";
    public static final String ANSI_YELLOW = "\u001B[33m";
    public static final String ANSI_BLUE = "\u001B[34m";
    public static final String ANSI_PURPLE = "\u001B[35m";
    public static final String ANSI_CYAN = "\u001B[36m";
    public static final String ANSI_WHITE = "\u001B[37m";
    public static final String ANSI_BLACK_BACKGROUND = "\u001B[40m";
    public static final String ANSI_RED_BACKGROUND = "\u001B[41m";
    public static final String ANSI_GREEN_BACKGROUND = "\u001B[42m";
    public static final String ANSI_YELLOW_BACKGROUND = "\u001B[43m";
    public static final String ANSI_BLUE_BACKGROUND = "\u001B[44m";
    public static final String ANSI_PURPLE_BACKGROUND = "\u001B[45m";
    public static final String ANSI_CYAN_BACKGROUND = "\u001B[46m";
    public static final String ANSI_WHITE_BACKGROUND = "\u001B[47m";

    public static final String FG_BLACK = "30"; // <black></black>
    public static final String FG_RED = "31"; // <r></r>
    public static final String FG_GREEN = "32"; // <g></g>
    public static final String FG_YELLOW = "33"; // <y></y>
    public static final String FG_BLUE = "34"; // <b></b>
    public static final String FG_PURPLE = "35"; // <p></p>
    public static final String FG_CYAN = "36"; // <c></c>
    public static final String FG_WHITE= "37"; // <white></white>
    //    public static final String BG_GRAY = "100";
    public static final String FG_WHITE_1 = "38:5:255"; // <white1></white1>
    public static final String BG_GRAY_1 = "48:5:234"; // <b_gray1></b_gray1>
    public static final String BG_GRAY_2 = "48:5:236"; // <b_gray2></b_gray2>
    public static final String BG_BLACK = "40"; // <b_black></b_black>

    public static final String BOLD = "1"; // <bold></bold>
    public static final String FAINT = "2"; // <faint></faint>
    public static final String ITALIC = "3"; // <italic></italic>
    public static final String UNDERLINE = "4"; // <underline></underline>

    public static final String CucumberCtTag = green("#CucumberCT# ");

    public static String escape(String flag) {
        return ESC_START + flag + ESC_END;
    }

    public static String escape(String ... flags) {
        return Stream.of(flags)
                .filter(Objects::nonNull)
                .map(ZwsColorfulLogHelper::escape)
                .collect(Collectors.joining());
    }

    public static String render(String text, String ... flags) {
        if (SystemUtils.IS_OS_WINDOWS) {
            return escape(flags) + text + ANSI_RESET;
        } else {
            return text;
        }
    }

    public static void renderIn(StringBuilder buf, String text, String ... flags) {
        if (SystemUtils.IS_OS_WINDOWS) {
            buf.append(escape(flags)).append(text).append(ANSI_RESET);
        } else {
            buf.append(text);
        }
    }

    public static String render(char text, String ... flags) {
        if (SystemUtils.IS_OS_WINDOWS) {
            return escape(flags) + text + ANSI_RESET;
        } else {
            return "" + text;
        }
    }

    public static void renderIn(StringBuilder buf, Object[] objs, String ... flags) {
        if (SystemUtils.IS_OS_WINDOWS) {
            buf.append(escape(flags));
        }
        for (Object obj : objs) {
            if (obj instanceof char[] ca) {
                buf.append(ca);
            } else if (obj instanceof ZwsRenderableStringSegment segment) {
                segment.render(buf);
            } else {
                buf.append(obj);
            }
        }
        if (SystemUtils.IS_OS_WINDOWS) {
            buf.append(ANSI_RESET);
        }
    }

    public static void renderIn(StringBuilder buf, char text, String ... flags) {
        if (SystemUtils.IS_OS_WINDOWS) {
            buf.append(escape(flags)).append(text).append(ANSI_RESET);
        } else {
            buf.append(text);
        }
    }

    public static String black(String text) {
        return render(text, FG_BLACK);
    }

    public static String red(String text) {
        return render(text, FG_RED);
    }

    public static String green(String text) {
        return render(text, FG_GREEN);
    }

    public static String yellow(char text) {
        return render(text, FG_YELLOW);
    }

    public static String yellow(String text) {
        return render(text, FG_YELLOW);
    }

    public static String blue(String text) {
        return render(text, FG_BLUE);
    }

    public static String purple(String text) {
        return render(text, FG_PURPLE);
    }

    public static String cyan(String text) {
        return render(text, FG_CYAN);
    }

    public static String white(String text) {
        return render(text, FG_WHITE);
    }

    public static String fill(char c, int len) {
        char[] chars = new char[len];
        Arrays.fill(chars, c);
        return new String(chars);
    }

    public static String center(String text, int len) {
        int count = text.codePointCount(0, text.length());
        int remaining = len - count;
        int left = remaining / 2;
        int right = remaining / 2 + (remaining & 0x01);

        char[] leftArray = new char[left];
        Arrays.fill(leftArray, ' ');
        char[] rightArray = new char[right];
        Arrays.fill(rightArray, ' ');
        return new String(leftArray) + text + new String(rightArray);
    }

}
